///////
#ifndef GITEE_ENHANCEUTILS_FS_HPP
#define GITEE_ENHANCEUTILS_FS_HPP
#include "string_view.hpp"
#include <cerrno>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>

namespace gitee {

std::string BaseName(gitee::string_view sv);
std::string DirName(gitee::string_view sv);
namespace perms {
enum Permissions : mode_t {
  none = 0,

  owner_read = 0400,
  owner_write = 0200,
  owner_exec = 0100,
  owner_all = 0700,

  group_read = 040,
  group_write = 020,
  group_exec = 010,
  group_all = 070,

  others_read = 04,
  others_write = 02,
  others_exec = 01,
  others_all = 07,

  all = 0777,

  set_uid = 04000,
  set_gid = 02000,
  sticky_bit = 01000,
  mask = 07777,
  unknown = 0xFFFF,
};
}
std::vector<gitee::string_view> SplitPath(gitee::string_view sv);
bool MakeDirRecurseFullPath(gitee::string_view dir, mode_t mode = perms::all);

inline bool PathDirExists(const char *p) {
  struct stat st;
  return (stat(p, &st) == 0 && S_ISDIR(st.st_mode) != 0);
}

struct DirBuffer {
  DirBuffer(gitee::string_view cur) {
    raw.resize(cur.size() + 256);
    raw.assign(cur.data(), cur.size()).push_back('/');
    rawsize = raw.size();
  }
  DirBuffer(const DirBuffer &) = delete;
  DirBuffer &operator=(const DirBuffer &) = delete;
  void Append(gitee::string_view sub) {
    raw.resize(rawsize);
    raw.append(sub.data(), sub.size());
  }
  gitee::string_view sv() const { return raw; }
  const char *data() const { return raw.data(); }
  std::string raw;
  size_t rawsize{0};
};

inline bool DirSkipFaster(const char *dn) {
  return (dn[0] == '.' && (dn[1] == '\0' || (dn[1] == '.' && dn[2] == '\0')));
}
bool RecurseRmdir(gitee::string_view dir);

}; // namespace gitee

#endif
